//----------------------------------------------------------------------------------------------------------------------
// Copyright (c) 2012 James Whitworth
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the \"Software\"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
//----------------------------------------------------------------------------------------------------------------------

// This will be scripts directory location relative to the current working directory.
//
_SCRIPTS_PATH <- ""
_CODEGEN_SCRIPT <- null
_OPTIONS <- ""

// info.src will be this filename plus a path if there is one, ie. "scripts/codegen.nut".
//
local info = getstackinfos(1)

// Check for the basic case of the current working directory being the scripts path.
//
if (info.src != "codegen.nut")
{
  // Build a regexp for matching the path section of the filename.
  //
  local expression = regexp("(.*)codegen.nut")
  local results = expression.capture(info.src)

  // Check we have some valid results.
  //
  if (results == null || results.len() < 1)
  {
    throw "unable to determine the scripts directory when trying to include other codegen-scripts"
  }

  // Trim the scripts path from info.src using the regexp match.
  //
  _SCRIPTS_PATH = info.src.slice(0, results[1].end)
}

// Now we know the scripts directory relative to the current working directory
// include all the other script files.
//
dofile(format("%scodegen-options.nut", _SCRIPTS_PATH), true)
dofile(format("%scodegen-base.nut", _SCRIPTS_PATH), true)
dofile(format("%scodegen-class.nut", _SCRIPTS_PATH), true)
dofile(format("%scodegen-parameter.nut", _SCRIPTS_PATH), true)
dofile(format("%scodegen-functionbody.nut", _SCRIPTS_PATH), true)
dofile(format("%scodegen-function.nut", _SCRIPTS_PATH), true)
dofile(format("%scodegen-file.nut", _SCRIPTS_PATH), true)
dofile(format("%scodegen-mocks.nut", _SCRIPTS_PATH), true)
dofile(format("%scodegen-serialisation.nut", _SCRIPTS_PATH), true)
dofile(format("%scodegen-tests.nut", _SCRIPTS_PATH), true)

if (!parse_command_line(vargv))
{
  display_usage_text()
  return 1
}

if (_OPTIONS["help"])
{
  if (vargv.len() > 1)
  {
    print("encountered '-help' option, ignoring all other options.\n\n")
  }
  display_usage_text()
  return 0
}

if (_OPTIONS["verbose"])
{
  display_verbose_text()
}

assert(type(_CODEGEN_SCRIPT) == "string")

local path = ""
local include_path = ""
local filename = _OPTIONS["file"]
local fileext = ""

// break up the specified file in to directory and file parts
//
{
  local expression = regexp(@"([^\\/]*$)")
  local results = expression.capture(_OPTIONS["file"])
  if (results)
  {
    path = _OPTIONS["file"].slice(0, results[1].begin - 1)
    filename = _OPTIONS["file"].slice(results[1].begin, results[1].end)
  }
}

// remove everything before include/ from path so it can be used as the include path
//
{
  local include_string = "include"
  local index = path.find(include_string)
  if (index != null)
  {
    include_path = path.slice(index + include_string.len() + 1)
  }
  else
  {
    include_path = path
  }
}

// break up the file part in to file name and extension parts
//
{
  local expression = regexp(@"\.(.*$)")
  local results = expression.capture(filename)
  if (results)
  {
    fileext = filename.slice(results[1].begin, results[1].end)
    filename = filename.slice(0, results[1].begin - 1)
  }
  else
  {
    switch (_OPTIONS["type"])
    {
    case "header":
      fileext = "h"
      break
    case "inline":
      fileext = "inl"
      break
    case "source":
      fileext = "cpp"
      break
    }
  }
}

local generated_file = File(filename, include_path, _OPTIONS["author"])
assert(generated_file)

local compiled_script = loadfile(_CODEGEN_SCRIPT, true)
assert(compiled_script)
try
{
  compiled_script(generated_file)
}
catch (err)
{
  print(err)
  return 2
}

local output_stream = OutputFileStream(format("%s/%s.%s", path, filename, fileext))
assert(output_stream)

switch (_OPTIONS["type"])
{
case "header":
  generated_file.write_header(output_stream)
  break
case "inline":
  generated_file.write_inline(output_stream)
  break
case "source":
  generated_file.write_source(output_stream)
  break
}

return 0